.Dd $Mdocdate$
.Dt NVC 1
.Os
.Sh NAME
.Nm nvc
.Nd VHDL Compiler and Simulator
.\" ------------------------------------------------------------
.\" Synopsis
.\" ------------------------------------------------------------
.Sh SYNOPSIS
.Nm
.Fl a Ar
.Nm
.Fl e
.Fa unit
.Nm
.Fl r
.Fa unit
.\" ------------------------------------------------------------
.\" Description
.\" ------------------------------------------------------------
.Sh DESCRIPTION
.Nm
is an implementation of the VHDL language as defined by IEEE standard
1076-1993 and later revisions.
.Pp
Simulating a design typically involves three steps: analysing one or
more source files into the work library; elaborating a top-level design
unit; and finally running the elaborated design.
.Pp
.Nm
accepts three kinds of options: global options; commands; and options
specific to the command.  Global options must be placed before the
command and specific options must be placed after the command.
.\"
.Ss Commands
.Bl -tag -width Ds
.\" -a
.It Fl a Ar
Analyse one or more files into the work library.  Reads from standard
input if
.Ar file
is
.Ql - .
.\" -e
.It Fl e Ar unit
Elaborate a previously analysed top level design unit.
.\" -r
.It Fl r Ar unit
Execute a previously elaborated top level design unit.
.\" -i
.It Fl i Bo Ar unit Bc
Start an interactive TCL shell, optionally with
.Ar unit
loaded.
.\" --cover-export
.It Fl \-cover-export Ar
Export collected coverage information from the internal database format
to an external format such as Cobertura XML.
.\" --cover-merge
.It Fl \-cover-merge Ar
Merge multiple coverage databases into a single database.
.\" --cover-report
.It Fl \-cover-report Ar
Generate an HTML report from a coverage database.
.\" --do
.It Fl \-do Bo Ar unit Bc Ar script
Evaluate a batch TCL script, optionally with
.Ar unit
loaded.
.\" --init
.It Fl \-init
Initialise the working library directory.  This is not normally
necessary as the library will be automatically created when using other
commands such as
.Fl a .
.\" --install
.It Fl \-install Ar package
Execute scripts to compile common verification frameworks and FPGA
vendor libraries.
.\" --list
.It Fl \-list
Print all analysed and elaborated units in the work library.
.\" --print-deps
.It Fl \-print-deps Ar unit ...
Print dependencies of
.Ar unit
in Makefile format.
.El
.\"
.Pp
.\" TODO: move this to the EXAMPLES section
Commands can be chained together arbitrarily and the top-level unit
name need only be specified once.  For example to analyse a file
.Ql source.vhd
and then elaborate and run a top-level entity
.Ql tb :
.Bd -literal -offset indent
$ nvc -a source.vhd -e tb -r
.Ed
.Pp
Note how the
.Ar unit
argument for the
.Fl r
command is taken from the earlier
.Fl e
command.
.\" ------------------------------------------------------------
.\" Global options
.\" ------------------------------------------------------------
.Ss Global options
.Bl -tag -width Ds
.\" --help
.It Fl h , -help
Display usage summary.
.\" -H
.It Fl H Ar size
Set the maximum size in bytes of the simulation heap.  This area of
memory is used for temporary allocations during process execution and
dynamic allocations by the VHDL
.Ql new
operator.  The
.Ar size
parameter takes an optional k, m, or g suffix to indicate kilobytes,
megabytes, and gigabytes respectively.  The default size is 16
megabytes.
.\" --ieee-warnings
.It Fl \-ieee-warnings= Ns Bo Cm on Ns | Ns Cm off Ns | Ns Cm off-at-0 Bc
Enable or disable warning messages from the standard IEEE packages.  The
.Cm off-at-0
option disables warnings in the first time step only.  The default is
warnings enabled.
.\" --ignore-time
.It Fl \-ignore-time
Do not check the timestamps of source files when the corresponding
design unit is loaded from a library.
.\" --load
.It Fl \-load= Ns Ar plugin
Loads a VHPI plugin from the shared library
.Ar plugin .
See section
.Sx VHPI
for details on the VHPI implementation.
.\" -L
.It Fl L Ar path
Add
.Ar path
to the list of directories to search for libraries.  See the
.Sx LIBRARIES
section below for details.
.\" -M
.It Fl M Ar size
Set the maximum amount of memory in bytes used for the internal
representations of design units.  The default is 16 megabytes but this
may be insufficient when elaborating a large design.  The
.Ar size
parameter takes an optional k, m, or g suffix to indicate kilobytes,
megabytes, and gigabytes respectively.  For example
.Fl M64m
for 64 megabytes.
.\" --map
.It Fl \-map Ns = Ns Ar name Ns : Ns Ar path
Specify exactly the location of the logical library
.Ar name .
Libraries mapped in this way will not use the normal search path.
.\" --messages
.It Fl \-messages Ns = Ns Bo Cm full Ns | Ns Cm compact Bc
Select the format used for printing error and informational messages.
The default full message format is designed for readability whereas the
compact messages can be easily parsed by tools.
.\" --seed
.It Fl \-seed Ns = Ns Ar N
Seed for random number generation.  Affects the
.Ql get_random
function in the
.Ql nvc.random
package, the
.Fl \-shuffle
option, and PSL union expressions.
.\" --std
.It Fl \-std Ns = Ns Ar rev
Select the VHDL standard revision to use.  VHDL standard revisions are
commonly referred to by the year they were published.  For example IEEE
1076-1993 is known as VHDL-93.  Specify either the full year such as
1993 or just the last two digits such as 93.  The accepted revisions are
1993, 2000, 2002, 2008, 2019.  Note there is very limited supported
VHDL-2019 at present and VHDL-87 is not supported.  The default standard
revision is VHDL-2008.
.\" --stderr
.It Fl \-stderr Ns = Ns Ar level
Print error messages with the given severity or higher to
.Ql stderr
instead of
.Ql stdout .
The default is to print all messages to
.Ql stderr .
Valid levels are
.Cm note ,
.Cm warning ,
.Cm error ,
.Cm failure ,
and
.Cm none .
.\" --version
.It Fl v , -version
Display version and copyright information.
.\" --vhpi-debug
.It Fl \-vhpi-debug
Report any VHPI errors as diagnostic messages on the console.  Normally
these are only returned through the
.Fn vhpi_check_error
function.
.\" --vhpi-trace
.It Fl \-vhpi-trace
Trace VHPI calls and events.  This can be useful for debugging VHPI
plugins.
.\" --work
.It Fl \-work Ns = Ns Ar name , Fl \-work Ns = Ns Ar name Ns : Ns Ar path
Use
.Ar name
as the work library.  The second variant explicitly specifies the
location of the library.  See the
.\"
.Sx LIBRARIES
section below for details.
.El
.\" ------------------------------------------------------------
.\" Analysis options
.\" ------------------------------------------------------------
.Ss Analysis options
.Bl -tag -width Ds
.\" --check-synthesis
.It Fl \-check\-synthesis
Issue warnings for common coding mistakes that may cause problems during
synthesis such as missing signals from process sensitivity lists.
.\" -D, --define
.It Fl D Ar name Ns [= Ns Ar value ] , Fl \-define Ns = Ns Ar name Ns \
[= Ns Ar value ]
Define a conditional analysis identifier (VHDL-2019) or preprocessor
macro (Verilog).  This option can be used multiple times to define
multiple identifiers or macros.  When
.Ar value
is ommited, the macro value is the empty string ("").
.\" --error-limit
.It Fl \-error-limit Ns = Ns Ar num
Stop after reporting
.Ar num
errors.  The default is 20.  Zero allows unlimited errors.
.\" -f, --files
.It Fl f Ar list , Fl \-files Ns = Ns Ar list
Read the list of source files to analyse from
.Ar list
which is a text file containing one file name per line.
If
.Ar list
is
.Ql \-
then reads from the standard input instead.
Comments starting with
.Ql #
are ignored.  References to environment variables such as
.Ql $FOO
are automatically expanded.  This argument may also be passed as
.Ar @list
for compatibility with other tools.
.\" -I
.It Fl I Ar dir
Add
.Ar dir
to the list of directories searched when processing the Verilog
.Ql `include
directive.
.\" --keywords
.It Fl \-keywords Ns = Ns Ar version
Use the set of keywords from the given Verilog or System Verilog
standard version.  The set of allowed versions is the same as those
accepted by the
.Ql `begin_keywords
directive.  For example
.Ql "1364-2001"
or
.Ql "1800-2017" .
In the absence of this option or a
.Ql `begin_keywords
directive, the default is
.Ql "1364-2001"
for files with a
.Ql .v
extension, and
.Ql "1800-2023"
for files with a
.Ql .sv
extension.
.\" --no-save
.It Fl \-no\-save
Do not save analysed design units to the working library.  This can be
used to quickly check for syntax and type errors.
.\" --preserve-case
.It Fl \-preserve\-case
Retain the original spelling of VHDL identifiers instead of converting
to a canonical upper-case form.  This is an experimental option and may
lead to incorrect behaviour.
.\" --psl
.It Fl \-psl
Enable parsing of PSL directives in comments.
.\" --relaxed
.It Fl \-relaxed
Disable certain pedantic LRM conformance checks or rules that were
relaxed by later standards.  See the
.Sx RELAXED RULES
section below for details.
.\" --single-unit
.It Fl \-single\-unit
Treat all Verilog source files given on the command line as a single
compilation unit.  This means macros declared in one file are visible in
all subsequent files.
.El
.\" ------------------------------------------------------------
.\" Elaboration options
.\" ------------------------------------------------------------
.Ss Elaboration options
.Bl -tag -width Ds
.\" --cover
.It Fl \-cover
Enable code coverage reporting (see the
.Sx CODE COVERAGE
section below).
.\" --cover-file
.It Fl \-cover-file= Ns Ar file
Specify the file name of the output coverage database.  Defaults to the
name of the top-level unit with a
.Ql .ncdb
extension.
.\" --cover-spec
.It Fl \-cover-spec= Ns Ar sfile
Specify design part where code coverage is collected by
.Ar sfile
coverage specification file
(see the
.Sx CODE COVERAGE
section below).
.\"
.It Fl g Ar name Ns = Ns Ar value
Override generic
.Ar name
with
.Ar value .
Integers, enumeration literals, and string literals are supported.
Generics in internal instances can be overridden by giving the full
dotted path to the generic.  For example
.Fl g\ I=5 ,
.Fl g\ INIT='1' ,
and
.Fl g\ UUT.STR="hello" .
.\" --jit
.It Fl j , Fl \-jit
Normally
.Nm
compiles all code ahead-of-time during elaboration.
The
.Fl \-jit
option defers native code generation until run-time where each function
will be compiled separately on a background thread once it has been has
been executed often enough in the interpreter to be deemed worthwhile.
This dramatically reduces elaboration time at the cost of increased
memory and CPU usage while the simulation is executing.  This option is
beneficial for short-running simulations where the performance gain from
ahead-of-time compilation is not so significant.
.\" --no-collapse
.It Fl \-no-collapse
Do not collapse ports into a single signal.  Normally if a signal at one
level in the hierarchy is directly connected to another signal in a
lower level via a port map, the signals are
.Dq collapsed
and only the signal in the upper level is preserved.  The
.Fl \-no-collapse
option disables this optimisation and preserves both signals.  This
improves debuggability at the cost of some performance.
.\" --no-save
.It Fl \-no-save
Do not save the elaborated design and other generated files to the
working library.  This is only really useful in combination with the
.Fl r
option.  For example:
.Bd -literal -offset indent
$ nvc -e --no-save tb -r
.Ed
.\"
.It Fl O0 , Fl 01 , Fl 02 , Fl O3
Set LLVM optimisation level.  Default is
.Fl O2 .
.\"
.It Fl V , Fl \-verbose
Prints resource usage information after each elaboration step.
.El
.\" ------------------------------------------------------------
.\" Runtime options
.\" ------------------------------------------------------------
.Ss Runtime options
.Bl -tag -width Ds
.\" --dump-arrays
.It Fl \-dump-arrays Ns Op =N
Include memories and nested arrays in the waveform data.  This is
disabled by default as it can have significant performance, memory, and
disk space overhead.  With optional argument
.Ar N
only arrays with up to this many elements will be dumped.
.\" --exit-severity
.It Fl \-exit-severity Ns = Ns Ar level
Terminate the simulation after an assertion failures of severity greater
than or equal to
.Ar level .
Valid levels are
.Cm note ,
.Cm warning ,
.Cm error ,
and
.Cm failure .
The default is
.Cm failure .
.Pp
This option also overrides the minimum severity level which causes the
program to return a non-zero status code.
The default is
.Cm error
which allows assertion violations to be detected easily.
.\" --format
.It Fl \-format= Ns Ar fmt
Generate waveform data in format
.Ar fmt .
Currently supported formats are:
.Cm fst
and
.Cm vcd .
The FST format is native to
.Xr gtkwave 1 .  FST is preferred over VCD due its
smaller size and better performance.  VCD is a very widely used format
but has limited ability to represent VHDL types and the performance is
poor: select this only if you must use the output with a tool that does
not support FST.  The default format is FST if this option is not
provided.  Note that GtkWave 3.3.79 or later is required to view the FST
output.
.\" --gtkw
.It Fl g , Fl \-gtkw Ns Op = Ns Ar file
Write a
.Xr gtkwave 1
save file containing every signal in the design hierarchy in declaration
order with separators for each scope.
This only makes sense in combination with the
.Fl \-wave
option.
.\" --include, --exclude
.It Fl \-include= Ns Ar glob , Fl \-exclude= Ns Ar glob
Signals that match
.Ar glob
are included in or excluded from the waveform dump.  See section
.Sx SELECTING SIGNALS
for details on how to select particular signals.  These options can be
given multiple times.
.\" --shuffle
.It Fl \-shuffle
Run processes in random order.  The VHDL standard does not specify the
execution order of processes and different simulators may exhibit subtly
different orderings.  The
.Fl \-shuffle
option can help to find and debug code that inadvertently depends on a
particular process execution order.  This option should only be used
during debug as it incurs a significant performance overhead as well as
introducing potentially non-deterministic behaviour.
.\" --stats
.It Fl \-stats
Print a summary of the time taken and memory used at the end of the run.
.\" --stop-delta
.It Fl \-stop-delta Ns = Ns Ar N
Stop after
.Ar N
delta cycles.  This can be used to detect zero-time loops in your model.
The default is 10000 if not specified.  Setting this to zero disables
the delta cycle limit.
.\" --stop-time
.It Fl \-stop-time Ns = Ns Ar T
Stop the simulation after the given time has elapsed.  Format of
.Ar T
is an integer followed by a time unit in lower case.  For example
.Cm 5ns
or
.Cm 20ms .
.\" --trace
.It Fl \-trace
Trace simulation events.  This is usually only useful for debugging the
simulator.
.\" --wave
.It Fl w , Fl \-wave Ns Op = Ns Ar file
Write waveform data to
.Ar file .
The file name is optional and if not specified will default to the name
of the top-level unit with the appropriate extension for the waveform
format.  The waveform format can be specified with the
.Fl \-format
option.  By default all signals in the design will be dumped: see the
.Sx SELECTING SIGNALS
section below for how to control this.
.El
.\" ------------------------------------------------------------
.\" Coverage export options
.\" ------------------------------------------------------------
.Ss Coverage export options
.Bl -tag -width Ds
.\" --format
.It Fl \-format= Ns Ar format
Selects one of the following output file formats:
.Bl -tag -width "cobertura"
.It Cm cobertura
Cobertura XML format widely supported by CI systems.
.It Cm xml
Simple XML dump of the coverage database contents.  The schema is liable
to change between releases.
.El
.\" --output
.It Fl o , Fl \-output= Ns Ar file
Write output to
.Ar file .
If this option is not specified the standard output stream is used.
.\" --relative
.It Fl \-relative Ns Op = Ns Ar path
Strip
.Ar path
or the current working directory from the front of any absolute path
names in the output.
.El
.\" ------------------------------------------------------------
.\" Coverage merge options
.\" ------------------------------------------------------------
.Ss Coverage merge options
.Bl -tag -width Ds
.\" --output
.It Fl o , Fl \-output= Ns Ar file
File name of output coverage database.
.\" --merge-mode
.It Fl m , Fl \-merge-mode= Ns Ar mode
Where
.Ar mode
can be one of:
.Ar union ,
.Ar intersect
.El
.\" ------------------------------------------------------------
.\" Coverage report options
.\" ------------------------------------------------------------
.Ss Coverage report options
.Bl -tag -width Ds
.\" --output
.It Fl o , Fl \-output= Ns Ar dir
Name of output directory where HTML files will be generated.
.It Fl \-exclude-file= Ns Ar efile
Apply commands in
.Ar efile
exclude file when generating code coverage report.
.It Fl \-dont-print= Ns Ar options
When set, NVC does not include code coverage details specified by
.Ar options
in the code coverage report.
.Ar options
is comma separated list of the following values:
.Bl -tag -width "uncovered"
.It Cm covered
Does not include covered items.
.It Cm uncovered
Does not include uncovered items.
.It Cm excluded
Does not include excluded items.
.El
.It Fl \-item-limit= Ns Ar limit
NVC displays maximum
.Ar limit
items of single type (covered, uncovered, excluded) in a single
hierarchy in the code coverage report.  Each Bin is counted as one item.
The default value of
.Ar limit
is 5000.
.It Fl \-per-file
Create source file code coverage report instead of hierarchy coverage report.
.El
.\" ------------------------------------------------------------
.\" Install options
.\" ------------------------------------------------------------
.Ss Install options
.Bl -tag -width Ds
.\" --dest
.It Fl \-dest= Ns Ar dir
Compile libraries into directory
.Ar dir
instead of the default
.Pa $HOME/.nvc/lib .
.\" --posix
.El
.\" ------------------------------------------------------------
.\" Libraries
.\" ------------------------------------------------------------
.Sh LIBRARIES
A library is a directory containing analysed design units and other
files generated by
.Nm .
The default library is called "work" and is placed in a directory also
called
.Em work .
Note that VHDL also has a concept of the "work library" where the
current library can be referred to by the alias
.Em work .
This confusing behaviour is an unfortunate hangover from the proprietary
tools the author used prior to writing
.Nm .
.Pp
The name and physical location of the work library is controlled by the
.Fl \-work
global option.  In the simple case of
.Fl \-work Ns = Ns Ar name
the library name is
.Ql name
and the physical location is a directory
.Pa name
relative to the current working directory.  The physical location can be
specified explicitly using
.Fl \-work Ns = Ns Ar name Ns : Ns Ar path
where
.Ar path
is the directory name.
On Windows the
.Li ;
character can be used instead of
.Li :
as a separator.
.Pp
The following examples should make this behaviour clear:
.Bd -literal -offset indent
$ nvc --work=mylib ...
.Ed
.Pp
The work library is named
.Ql mylib
and is mapped to a directory with the same name in the current working
directory.
.Bd -literal -offset indent
$ nvc --work=mylib:somedir ...
.Ed
.Pp
The work library is named
.Ql mylib
and is mapped to a directory
.Pa somedir
in the current working directory.
.Bd -literal -offset indent
$ nvc --work=mylib:/foo/bar ...
.Ed
.Pp
The work library is named
.Ql mylib
and is mapped to the absolute path
.Pa /foo/bar .
.Pp
Concurrent access to a single library by multiple processes is
completely safe and protected by a lock in the filesystem using
.Xr flock 2
that allows multiple concurrent readers but only a single writer.
.\" ------------------------------------------------------------
.\" TCL SCRIPTING
.\" ------------------------------------------------------------
.Sh TCL SCRIPTING
.Nm
supports both interactive and batch scripting using TCL.  This must be
enabled at compile time using
.Ql --enable-tcl .
The TCL environment supports standard TCL commands, the
.Ql tcllib
extension library, and a number of NVC-specific commands.  Use the
.Cm help
command in the interactive environment
.Ns ( Fl i Ns )
to list these.
.\" ------------------------------------------------------------
.\" CODE COVERAGE
.\" ------------------------------------------------------------
.Sh CODE COVERAGE
.Nm
can collect code coverage data while the simulation is executing.
NVC counts coverage in so called coverage bins. Each coverage bin
counts from 0, and increments each time coverage kind specific
criteria are met. Coverage bins saturate at 2147483647.
The following coverage kinds are supported:
.Bl -bullet
.It
.Cm statement
- For each statement, NVC creates coverage bin. When a statement
  is executed, coverage bin is incremented.
.It
.Cm branch
- For each point where code diverges (if/else, case, when/else,
with/select statements), NVC creates coverage bin.  If branch can be
evaluated to both true and false, NVC creates two coverage bins for such
branch (one for each of true/false). When a branch is evaluated,
its coverage bin is incremented.
.It
.Cm toggle
- Each signal of type derived from
.Ql std_logic
(including nested arrays) creates two coverage bins (to track
\fB0\fP -> \fB1\fP and \fB1\fP -> \fB0\fR transitions). When a
signal toggles, coverage bin is incremented.
.It
.Cm expression
- NVC creates multiple coverage bins for combinations of input operands
of the following logical operators:
.Ql and Ns ,
.Ql nand Ns ,
.Ql or Ns ,
.Ql nor Ns ,
.Ql xor Ns ,
.Ql xnor Ns ,
such that propagation of operand values causes the expression result to
change its value.  Further, NVC creates two coverage bins for evaluating
expression result to
.Ql True
and
.Ql False
for the following operators:
.Ql = Ns ,
.Ql /= Ns ,
.Ql > Ns ,
.Ql < Ns ,
.Ql <= Ns ,
.Ql >= Ns ,
.Ql not Ns .
NVC collects expression coverage also on overloaded logic operators from
.Ql ieee.std_logic_1164
library.  It tracks combinations of input values to logic operators for
.Ql std_logic
operand type.  NVC does not collect expression coverage for VHDL 2008
overloaded operands for
.Ql std_logic_vector
type. When expression evaluates, coverage bin corresponding to combination
of expression operands, or expression result is incremented.
.It
.Cm fsm-state
- NVC tracks if states of Finite State Machines (FSMs) are visited. NVC creates
a coverage bin for each state of an FSM. NVC considers internal signals of
all user-defined enum types as FSMs. NVC does not consider port signals or
variables as an FSM. When a signal recognized as FSM changes its value,
coverage bin for new state value is incremented.
.It
.Cm functional
- NVC creates a coverage bin for each:
.Bl -bullet
.It
PSL
.Ql cover
directive. When a PSL sequence in the cover directive completes, coverage bin is incremented.
.It
Functional coverage bin from third party libraries (e.g. OSVVM)
.El
.El
.Pp
Collection of each coverage kind can be enabled separately at elaboration time:
.Bd -literal -offset indent
$ nvc -e --cover=statement,branch,toggle,expression <top>
.Ed
.Pp
If no coverage type is specified as an argument of
.Fl \-cover ,
all coverage types are collected.  After the simulation has finished the
coverage data is written to a coverage database file.  By default this
is the name of the top-level unit with an
.Ql .ncdb
extension in the current working directory, but can be changed with the
.Fl \-cover\-file
elaboration option.
.Ss Code coverage merging
To merge code coverage data from multiple simulations run:
.Bd -literal -offset indent
$ nvc --cover-merge -o merged.ncdb first.ncdb second.ncdb third.ncdb ...
.Ed
.Pp
During code coverage merging, NVC sums together coverage bins with equal
hierarchical paths in the elaborated design.
.Pp
NVC supports different modes of merging. The merge mode controls what NVC
does if a coverage database that is being merged (new) contains a coverage
item that is not present in the coverage database being merged into (old).
The merge mode can be selected by a
.Cm --merge-mode=mode
option where
.Cm mode
can be one of:
.Bl -bullet
.It
.Cm union
- The item is added to the merged (old) database. This is the default mode.
.It
.Cm intersect
- The item is dropped from the merged (old) database.
.El
.Ss Generating code coverage report
To generate code coverage report in HTML format, run:
.Bd -literal -offset indent
$ nvc --cover-report -o report_dir merged.ncdb
.Ed
.Pp
The command above will generate a code coverage report in the
.Pa report_dir
directory.
Code coverage report shows whether a coverage bin is covered or uncovered.
A bin is covered when its counter is equal to, or higher than threshold
given by
.Cm --threshold-<value>
option of
.Cm --cover
elabortion switch.
NVC supports two kinds of code coverage reports:
.Bl -bullet
.It
.Cm hierarchy report -
Code coverage report contains code coverage summary for each design
hierarchy in simulated design. Code coverage data of a nested hierarchy
are added to data of hierarchy that instantiate the nested hierarchy.
.It
.Cm source file report -
Code coverage report contains code coverage summary for each source
file used in simulated design. If a single entity or module was instantiated
multiple times, code coverage data from all such instantiations are merged
and reported under one source file. If a source file was compiled, but
none of its entities, modules or packages were used in the simulated design,
such file is not shown in code coverage report.
.El
.Pp
By default NVC generates hierarchy code coverage report.
To generate source file code coverage report, add
.Cm --per-file
switch to
.Cm --cover-report
command.
.Pp
Code coverage merging and generating code coverage report can also be done
in a single command:
.Bd -literal -offset indent
$ nvc --cover-report -o html first.ncdb second.ncdb third.ncdb ...
.Ed
.Ss Additional code coverage options
NVC supports the following additional options to control coverage collection:
.Bl -bullet
.It
.Cm count-from-undefined
- When set, NVC also counts toggles from
.Cm U
/
.Cm X
to
.Cm 1
as
.Cm 0
to
.Cm 1
and toggles from
.Cm U
/
.Cm X
to
.Cm 0
as
.Cm 1
/
.Cm 0
during toggle coverage collection.
.It
.Cm count-from-to-z
- When set, NVC also counts toggles from/to
.Cm Z
to either of
.Cm 0/1
as valid
.Cm 0
->
.Cm 1
or
.Cm 1
->
.Cm 0
transitions.
.It
.Cm include-mems
- When set, NVC collects toggle coverage on multidimensional arrays or
nested arrays (array of array), disabled by default.
.It
.Cm ignore-arrays-from-<size>
- When set, NVC does not collect toggle coverage on arrays whose size is equal
to or larger than
.Cm <size>
.It
.Cm exclude-unreachable
- When set, NVC detects unreachable coverage bins and automatically excludes
them during code coverage report generation. NVC detects following
unreachable coverage items:
.Bl -bullet
.It
Toggle coverage on instance ports driven by constant value.
.It
Expression coverage bins where right side of the expression is not evaluated
due to left side value being sufficient to determine expression result.
This applies to following cases:
.Bl -bullet
.It
.Ql or
expression bin with LHS=True, RHS=False
.It
.Ql and
expression bin with LHS=False, RHS=True.
.El
.El
.It
.Cm fsm-no-default-enums
- When set, NVC by default does not consider signals of usr-define enum types
as FSMs. With this option, NVC can be forced to recognize FSMs only via
.Ql fsm-type
directive in coverage specification file.
.El
.Bl -bullet
.It
.Cm threshold-<value>
- A minimal value of coverage bin counter for coverage bin to be reported as
  covered. Default is 1.
.El
.Pp
All additional coverage options are passed comma separated to
.Fl \-cover
elaboration option, e.g.:
.Bd -literal -offset indent
$ nvc -e --cover=all,include-mems,count-from-undefined <top>
.Ed
.Pp
Coverage collection on parts of the code can be ignored via a comment
pragma, for example:
.Bd -literal -offset indent
case (sel) is
  when "00" => ...
  when "01" => ...
  when "10" => ...
  when "11" => ...
  -- coverage off
  when others => report "ERROR" severity failure;
  -- coverage on
end case;
.Ed
.Pp
In the example above, statement coverage for the
.Ql report
statement and branch coverage for
.Ql others
choice will not be collected.
.Pp
Toggle coverage collection on specific signals can be also disabled:
.Bd -literal -offset indent
-- coverage off
signal cnt : std_logic_vector(3 downto 0);
-- coverage on
.Ed
.Ss Coverage specification file
NVC can collect code coverage only on part of the simulated design.
When coverage specification file is passed during elaboration time,
NVC collects code coverage only as specified in this file. If
the file is ommited, NVC collects code coverage on whole design.
The format of commands in the coverage specification file is as follows:
.Bd -literal -offset indent
(+|-)block <ENTITY_NAME>
(+|-)hierarchy <HIERARCHY>
(+|-)fsm-type <TYPE>
.Ed
.Pp
An example of coverage specification file is following:
.Bd -literal -offset indent
# Placing '#' is treated as comment till end of line

# Example how to enable collecting code coverage on a hierarchy:
+hierarchy WORK.TOP.DUT_INST*

# Example how to disable collecting code coverage on a hierarchy:
-hierarchy WORK.TOP.DUT_INST.THIRD_PARTY_SUB_BLOCK_INST*

# Example how to enable collecting code coverage on entity or block:
+block async_fifo

# Example how to disable collecting code coverage on entity or block:
-block clock_gate_model

# Example how to force all signals of enum types named 'T_FSM_STATE'
# to be recognized as FSM
+fsm_type T_FSM_STATE

# Example how to force all signals of enum types with name matching
# 'T_*_FSM' pattern to be recognized as FSM
+fsm_type T_*_FSM

# Example how to force all signals of enum type named 'T_TRANSFER_TYPE'
# not to be recognized as an FSM
-fsm-type T_TRANSFER_TYPE
.Ed
.Pp
In coverage specification file
.Ql block
has priority over
.Ql hierarchy ,
disabled hierarchy / block (
.Ql -
) has priority over enabled hierarchy / block (
.Ql +
).
.Ss Exclude file
NVC can exclude any coverage bins when generating code coverage report.
When a coverage bin is excluded, it is counted as "Covered" in the
coverage summary and displayed in a dedicated group in the code coverage
report.  Format of commands in exclude file is following:
.Bd -literal -offset indent
exclude <HIERARCHY(.BIN)>
.Ed
.Pp
Where
.Ql <HIERARCHY>
is hierarchical path of the coverage bin in the elaborated design, and
.Ql BIN
is one of following bins:
.Bl -bullet
.It
.Cm BIN_TRUE
- Excludes "Evaluated to: True" bin.  Applicable to if/else branch,
when/else branch or expression.
.It
.Cm BIN_FALSE
- Excludes "Evaluated to: False" bin.  Applicable to if/else branch,
when/else branch or expression.
.It
.Cm BIN_CHOICE
- Excludes "Choice of:" bin.  Applicable to case/with branch choices.
.It
.Cm BIN_X_Y
- Excludes bins for combination of input operands (LHS, RHS) of an
expression.  Applicable to an expression for which combinations of input
operand values is tracked.
.Ql X ,
.Ql Y
shall be 0 or 1.  Excludes bin where LHS =
.Ql X
and RHS =
.Ql Y ,
see an example exclude file below.
.It
.Cm BIN_0_TO_1
- Excludes "Toggle from 0 to 1" bin.  Applicable to signal / port toggle
coverage.
.It
.Cm BIN_1_TO_0
- Excludes "Toggle from 1 to 0" bin.  Applicable to signal / port toggle
coverage.
.It
.Cm BIN_STATE.<ENUM_VALUE>
- Excludes
.Ql ENUM_VALUE
FSM state.
.El
.Pp
An example of exclude file:
.Bd -literal -offset indent
# Placing '#' is treated as comment till end of line

# Example how to exclude statement
# For statements BIN shall be ommited
exclude WORK.TOP._P1._S0._S3

# Example how to exclude all coverage items which match wildcard:
exclude WORK.TOP.SUB_BLOCK_INST.*

# Example how to exclude 4 coverage bins for combinations of input
# operands value (LHS, RHS) of an expression:
exclude WORK.TOP.XOR_GATE._S0._E0.BIN_0_0
exclude WORK.TOP.XOR_GATE._S0._E0.BIN_0_1
exclude WORK.TOP.XOR_GATE._S0._E0.BIN_1_0
exclude WORK.TOP.XOR_GATE._S0._E0.BIN_1_1

# Example which excludes the same items as previous example,
# but excludes all bins by a single command:
exclude WORK.TOP.XOR_GATE._S0._E0.*

# Example how to exclude branch 'Evaluated to: False' bin:
exclude WORK.TOP._P0._S0._B0.BIN_FALSE

# Example how to exclude toggle bin 'Toggle from 0 to 1' on
# a signal, and all toggle bins on a port of sub-instance:
exclude WORK.TOP.SIGNAL_NAME.BIN_0_TO_1
exclude WORK.TOP.SUB_BLOCK_INST.PORT_NAME.*

# Example how to exclude FSM state "ST_ERROR" where "ST_ERROR"
# is one of the enum values used to code the FSM.
exclude WORK.TOP.CONTROLLER.CURR_STATE.BIN_STATE.ST_ERROR
.Ed
.Ss Coverage folding
NVC supports merging code coverage of single entity / module
instantiated on multiple places in hierarchy. Such type of
coverage merging is called coverage folding. Coverage folding
is useful when simulating a complex DUT. If a sub-block of a
DUT has a logic that is hard to cover in DUT top level test-bench,
then creating a unit test for such sub-block is easy way to
achieve full sub-block coverage. The sub-block has different
hierarchy when simulated in DUT top level test-bench and in the
unit test. In DUT top level test-bench, the sub-block is
instantiated under the DUT. In the unit-test, sub-block is instantiated
directly. To merge coverage data from two such instantiations,
you can utilize coverage folding.
.Pp
Coverage folding is specified by
.Ql fold
command placed in Exclude file. The syntax of
.Ql fold
command is following:
.Bd -literal -offset indent
fold <DESTINATION_INSTANCE_HIERARCHY> <SOURCE_INSTANCE_HIERARCHY>
.Ed
where
.Ql <DESTINATION_INSTANCE_HIERARCHY>
is the destination hierarchy where the coverage data will be
merged and
.Ql <SOURCE_INSTANCE_HIERARCHY>
is the source hierarchy from which the coverage data will be
merged.
.Pp
When folding coverage, NVC merges coverage items similarly
as during regular merging (based on hierarchical path).
However, in case of folding, NVC strips
.Ql <DESTINATION_INSTANCE_HIERARCHY>
from the path of the destination coverage item, and strips
.Ql <SOURCE_INSTANCE_HIERARCHY>
from the source item. Thus NVC folds coverage items based on
matching suffix of their hierarchical path.
.Pp
An example of how folding can be specified is following.
Assume there is an entity
.Ql INSTR_CACHE
instantiated as:
.Bl -bullet
.It
.Ql I_INSTR_CACHE
instance in a testbench
.Ql TB_TOP
.It
.Ql DUT
instance in a unit test
.Ql CACHE_UNIT_TEST
.El
.Pp
.Ql TB_TOP
testbench is compiled into
.Ql TB_TOP_LIB
library. Unit test is compiled into
.Ql UNIT_TEST_LIB
library. The following command folds coverage items of
.Ql INSTR_CACHE
from
.Ql CACHE_UNIT_TEST
to
.Ql TB_TOP
:
.Bd -literal -offset indent
fold TB_TOP_LIB.TB_TOP.DUT.I_CPU_DATAPATH.I_INSTR_CACHE UNIT_TEST_LIB.CACHE_UNIT_TEST.DUT
.Ed
.Ss Code coverage limitations
When part of the design hierarchy is formed by an if-generate-else or
case-generate statement, the hierarchical path of implicit block
statements for each of the if-else branches or case choices is identical
unless the user provides an alternative label for each branch or choice.
For example:
.Bd -literal -offset indent
my_gen : case (op_kind) generate
when op_add => x <= a + b;
when op_sub => x <= a - b;
end generate my_gen;
.Ed
.Pp
Both assignment statements have a hierarchical path that ends with
.Ql .MY_GEN._P0._SO
and will not be considered distinct when merging.
To avoid this give each case branch a unique label:
.Bd -literal -offset indent
my_gen : case (op_kind) generate
when branch1: op_add => x <= a + b;
when branch2: op_sub => x <= a - b;
end generate my_gen;
.Ed
.Ss Additional Information
In coverage specification file and Exclude file
.Ql <ENTITY_NAME>
.
.Ql <HIERARCHY>
and
.Ql <TYPE>
are case-insensitive. You can get examples of exclude commands
from generated Code coverage report by clicking on
a "Get Exclude Command" button.
.\" ------------------------------------------------------------
.\" Relaxed rules
.\" ------------------------------------------------------------
.Sh RELAXED RULES
The
.Fl \-relaxed
analysis flag enables
.Dq relaxed rules
mode which downgrades the following errors to warnings:
.Bl -bullet
.It
Impure function called from pure function.
.It
File object declared in pure function.
.It
Default expression in object interface declaration is not globally
static.
.It
Shared variable is not of protected type in VHDL-2000 or later.
.El
.Pp
Additionally the following languages features from VHDL-2008 and later
are enabled in earlier standards:
.Bl -bullet
.It
Any visible explicitly declared operator always hides an implicit
operator regardless of the region in which it is declared.  This is
required to analyse code that uses the non-standard Synopsys
.Sy std_logic_arith
package.
.It
References to generics and array slices are allowed in locally static
expressions using the VHDL-2008 rules.
.It
Range bounds with
.Ql universal_integer
type are not required to be numeric literals or attributes.  This option
allows ranges such as
.Ql -1 to 1
in VHDL-1993 which otherwise must be written
.Ql integer'(-1) to 1 .
.El
.\" ------------------------------------------------------------
.\" Selecting signals
.\" ------------------------------------------------------------
.Sh SELECTING SIGNALS
Every signal object in an elaborated design has a unique hierarchical
path name.  In VHDL this can be accessed using the
.Ql PATH_NAME
attribute.
.Pp
A signal can be referred to using its full path name, for example
.Ql :top:sub:x ,
and
.Ql :top:other:x
are two different signals named
.Ql x
in the design.  The character
.Ql \&:
is a hierarchy separator.  The special character
.Ql *
is a wildcard that matches zero or more characters and may be used refer
to a group of signals.  For example
.Ql :top:*:x ,
.Ql *:x ,
and
.Ql :top:sub:* ,
all select both of the previous signals.
.\"
.Ss Restricting waveform dumps
Path names and globs can be used to exclude or explicitly include
signals in a waveform dump.  For simple cases this can be done using the
.Fl \-include
and
.Fl \-exclude
arguments.  For example
.Fl \-exclude= Ns Qq Ar :top:sub:*
will exclude all matching signals from the waveform dump.  Multiple
inclusion and exclusion patterns can be provided.
.Pp
Specifying large numbers of patterns on the command line quickly becomes
cumbersome.  Instead inclusion and exclusion patterns can be read from a
text file.  If the top-level unit name is
.Ql top
then inclusion patterns should be placed in a file called
.Pa top.include
and exclusion patterns in a file called
.Pa top.exclude .
These files should be in the working directory where the
.Ql nvc -r
command is executed.  The format is one glob per line, with comments
preceded by a
.Ql #
character.
.Pp
When both inclusion and exclusion patterns are present, exclusions have
precedence over inclusions.  If no inclusion patterns are present then
all signals are implicitly included.
.\" ------------------------------------------------------------
.\" VHPI
.\" ------------------------------------------------------------
.Sh VHPI
.Nm
supports a subset of VHPI allowing access to signal values and
events at runtime.  The standard VHPI header file
.In vhpi_user.h
will be placed in the system include directory as part of the
installation process.  VHPI plugins should be compiled as shared
libraries; for example:
.Bd -literal -offset indent
$ cc -shared -fPIC my_plugin.c -o my_plugin.so
$ nvc -r --load my_plugin.so my_tb
.Ed
.Pp
The plugin should define a global
.Va vhpi_startup_routines
which is a NULL-terminated list of functions to call when the plugin is
loaded:
.Bd -literal -offset indent
void (*vhpi_startup_routines[])() = {
   startup_1,
   startup_2,
   NULL
};
.Ed
.Pp
Functions defined in VHPI plugin libraries may be called from VHDL using
either the standard VHPI protocol or a simplified protocol similar to
.Xr ghdl 1
.
.Pp
To use the standard VHPI protocol the VHDL function should be declared
with the
.Ql FOREIGN
attribute giving the
.Qq object library name
and
.Qq model name
of the foreign function.
For example:
.Bd -literal -offset indent
function my_func (x : integer;
                  y : bit_vector;
                  z : std_logic) return integer is
begin
    report "should not reach here" severity failure;
end function;

attribute foreign of my_func : function is "VHPI my_lib my_func";
.Ed
.Pp
The VHPI plugin should then call
.Fn vhpi_register_foreignf
to register the foreign subprogram.
.Bd -literal -offset indent
static void my_func_cb(const vhpiCbDataT *cb_data_p) { ... }

vhpiForeignDataT my_func_data = {
   .kind = vhpiFuncF,
   .libraryName = "my_lib",
   .modelName = "my_func",
   .execf = my_func_cb,
};
vhpi_register_foreignf(&my_func_data);
.Ed
.Pp
To use the simplified protocol the VHDL the
.Ql FOREIGN
attribute should be specified with the keyword
.Ql VHPIDIRECT
and name of the function symbol exported from the plugin.
For example:
.Bd -literal -offset indent
attribute foreign of my_func : function is "VHPIDIRECT my_func";
.Ed
.Pp
Where
.Ql my_func
is a global function defined in the plugin library as follows.
.Bd -literal -offset indent
int32_t my_func(int32_t x, const uint8_t *y, int64_t y_len, uint8_t z);
.Ed
.Pp
Foreign procedures may be defined similarly:
.Bd -literal -offset indent
function my_proc (x : out integer; y : out bit_vector; z : std_logic);
attribute foreign of my_proc : function is "VHPIDIRECT my_proc";

void my_proc(int32_t *x, uint8_t *y, int64_t y_len, uint8_t z);
.Ed
.Pp
Note that scalar
.Ql out
parameters are passed by pointer.
.Pp
There is a simple mapping between VHDL and C types.
.Bl -tag -width "Unconstrained arrays"
.It Integers
The smallest C integer type that holds the full range of the VHDL type.
.It Reals
C
.Vt double
regardless of the range of the VHDL type.
.It Enumerated types
The smallest unsigned integer type that holds the full range of the VHDL
type.
.It Constrained arrays
Pointer to the element type.
.It Unconstrained arrays
Pointer to the element type followed by one
.Vt int64_t
length argument for each dimension.  Note that the bounds and direction
are not available and must be passed explicitly as separate arguments if
required.
.It Records
Not yet supported.
.El
.Pp
Here are several examples for common types:
.Bl -column "INTEGER range 1 to 5" -offset indent
.It Sy "VHDL type" Ta Sy "C type"
.It Li "INTEGER" Ta Vt int32_t
.It Li "INTEGER range 1 to 5" Ta Vt int8_t
.It Li REAL Ta Vt double
.It Li BOOLEAN Ta Vt uint8_t
.It Li "BIT_VECTOR(1 to 3)" Ta Vt "uint8_t *"
.It Li STD_LOGIC Ta uint8_t
.It Li STD_LOGIC_VECTOR Ta Vt "uint8_t *" , Vt "int64_t"
.El
.Pp
Foreign functions must not modify arrays passed as
.Ql in
arguments.  Additionally foreign subprograms must not retain any
pointers passed as arguments after the subprogram returns.  Violating
these rules will result in unpredictable and hard to debug behaviour.
.Sh ENVIRONMENT
.Bl -tag -width "NVC_CONCURRENT_JOBS"
.It Ev NVC_CONCURRENT_JOBS
Provides a hint for the number of concurrently executing simulations.
This allows
.Nm
to scale its worker thread count to avoid overloading the system.
This is set automatically by frameworks such as VUnit.
See
.Ev NVC_MAX_THREADS .
.It Ev NVC_COLORS
Controls whether
.Nm
uses ANSI colour escape sequences to print diagnostic messages.  The
possible values are
.Cm never ,
.Cm always ,
and
.Cm auto
which enables colour if stdout is connected to a terminal.
The default is
.Cm auto .
.It Ev NVC_MAX_THREADS
Limit the number of worker threads
.Nm
can create.
The default is either eight or the number of available CPUs, whichever
is smaller.
.El
.\" .Sh FILES
.\" .Sh EXIT STATUS
.\" For sections 1, 6, and 8 only.
.\" .Sh EXAMPLES
.Sh SEE ALSO
.Xr ghdl 1 ,
.Xr gtkwave 1
.\" .Sh STANDARDS
.\" .Sh HISTORY
.Sh AUTHORS
Written by
.An Nick Gasson Aq nick@nickg.me.uk
.\" .Sh CAVEATS
.Sh BUGS
Report bugs to
.Mt nick@nickg.me.uk
or using the GitHub issue tracker at
.Lk https://github.com/nickg/nvc/issues .
Please include enough information to reproduce the problem, ideally with
a small VHDL test case.
